package com.dftdla.server.handler;

import com.dftdla.dao.service.ChatUserService;
import com.dftdla.jwt.utils.JwtUtil;
import com.dftdla.server.session.Session;
import com.dftdla.utils.ChannelUtils;
import com.dftdla.utils.MessageUtil;
import com.dftdla.server.message.Message;
import com.dftdla.result.ResponseResult;
import com.dftdla.util.Code;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author 14501
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Resource
    private ChatUserService chatUserService;

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        String text = textWebSocketFrame.text();
        Message decode = MessageUtil.decode(text);
        log.info("解析指令：{}",decode);

        if(decode == null){
            channelHandlerContext.fireChannelRead(text);
            return;
        }

        boolean login = decode.getMessageType() == Message.LOGIN_REQUEST_MESSAGE;

        if(login || doAuth(decode.getToken(), channelHandlerContext.channel())){
            //如果不是登录指令，则说明token鉴权通过，我们设置一个userId给Message以替代ThreadLocal保存的UserId，这样不用再手动回收
            if(!login){
                decode.setUserId(Long.parseLong(JwtUtil.parseJWT(decode.getToken()).getSubject()));
            }
            //交给下面的Handler进行类型匹配
            channelHandlerContext.fireChannelRead(decode);
        }else{
            //鉴权未通过，关闭channel
            channelHandlerContext.writeAndFlush(new TextWebSocketFrame(new ResponseResult<String>(Code.USER_AUTH_ERROR).toString()));
            log.warn("非法的token!");
            ChannelUtils.close(channelHandlerContext.channel());
        }
    }

    /**
     * 鉴定token是否合法
     * @param token 待校验Auth
     * @return true合法
     */
    public boolean doAuth(String token, Channel channel){
        return chatUserService.doAuth(token,channel);
    }
}
